{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4bb251de-463e-4156-bcfc-9078721f6a8b",
   "metadata": {},
   "source": [
    "# Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0ae4a1f2-c40c-4c97-9c98-e8e1152a3f95",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List, Tuple, Optional\n",
    "\n",
    "import joblib\n",
    "import openai\n",
    "from joblib import parallel_config\n",
    "\n",
    "from burr.core import Application, ApplicationBuilder, Condition, State, action\n",
    "from burr.core.application import ApplicationContext\n",
    "from burr.tracking import LocalTrackingClient"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3e64255-0154-496b-b1cd-7821789e05b0",
   "metadata": {},
   "source": [
    "# Helper functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5d45a62a-3432-4159-a1a2-703ef8d91d3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def _query_llm(prompt: str) -> str:\n",
    "    \"\"\"Simple wrapper around the OpenAI API.\"\"\"\n",
    "    client = openai.Client()\n",
    "    return (\n",
    "        client.chat.completions.create(\n",
    "            model=\"gpt-4o\",\n",
    "            messages=[\n",
    "                {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
    "                {\"role\": \"user\", \"content\": prompt},\n",
    "            ],\n",
    "        )\n",
    "        .choices[0]\n",
    "        .message.content\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91a4a439-9d5e-4e6d-b287-0532abd3c19e",
   "metadata": {},
   "source": [
    "# Sub Application\n",
    "\n",
    "First let's write a sub-application. We're going to have it do two things:\n",
    "\n",
    "1. Write a poem (`write`)\n",
    "2. Provide suggestions (`edit`)\n",
    "\n",
    "We're going to wrap its creation in a function so we can create it within an application. Note that we pass in `__context` -- this allows us to wire the context through for tracking."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ce9afd4c-986a-4d19-b72a-67c1b2b7fa34",
   "metadata": {},
   "outputs": [],
   "source": [
    "@action(\n",
    "    reads=[\"feedback\", \"current_draft\", \"poem_type\", \"prompt\"],\n",
    "    writes=[\"current_draft\", \"draft_history\", \"num_drafts\"],\n",
    ")\n",
    "def write(state: State) -> Tuple[dict, State]:\n",
    "    \"\"\"Writes a draft of a poem.\"\"\"\n",
    "    poem_subject = state[\"prompt\"]\n",
    "    poem_type = state[\"poem_type\"]\n",
    "    current_draft = state.get(\"current_draft\")\n",
    "    feedback = state.get(\"feedback\")\n",
    "\n",
    "    parts = [\n",
    "        f'You are an AI poet. Create a {poem_type} poem on the following subject: \"{poem_subject}\".'\n",
    "    ]\n",
    "\n",
    "    if current_draft:\n",
    "        parts.append(f'Here is the current draft of the poem: \"{current_draft}\".')\n",
    "\n",
    "    if feedback:\n",
    "        parts.append(f'Please incorporate the following feedback: \"{feedback}\".')\n",
    "\n",
    "    parts.append(\n",
    "        f\"Ensure the poem is creative, adheres to the style of a {poem_type}, and improves upon the previous draft.\"\n",
    "    )\n",
    "\n",
    "    prompt = \"\\n\".join(parts)\n",
    "\n",
    "    draft = _query_llm(prompt)\n",
    "\n",
    "    return {\"draft\": draft}, state.update(\n",
    "        current_draft=draft,\n",
    "        draft_history=state.get(\"draft_history\", []) + [draft],\n",
    "    ).increment(num_drafts=1)\n",
    "\n",
    "\n",
    "@action(reads=[\"current_draft\", \"poem_type\", \"prompt\"], writes=[\"feedback\"])\n",
    "def edit(state: State) -> Tuple[dict, State]:\n",
    "    \"\"\"Edits a draft of a poem, providing feedback\"\"\"\n",
    "    poem_subject = state[\"prompt\"]\n",
    "    poem_type = state[\"poem_type\"]\n",
    "    current_draft = state[\"current_draft\"]\n",
    "\n",
    "    prompt = f\"\"\"\n",
    "    You are an AI poetry critic. Review the following {poem_type} poem based on the subject: \"{poem_subject}\".\n",
    "    Here is the current draft of the poem: \"{current_draft}\".\n",
    "    Provide detailed feedback to improve the poem. If the poem is already excellent and needs no changes, simply respond with an empty string.\n",
    "    \"\"\"\n",
    "\n",
    "    feedback = _query_llm(prompt)\n",
    "\n",
    "    return {\"feedback\": feedback}, state.update(feedback=feedback)\n",
    "\n",
    "\n",
    "@action(reads=[\"current_draft\"], writes=[\"final_draft\"])\n",
    "def final_draft(state: State) -> Tuple[dict, State]:\n",
    "    return {\"final_draft\": state[\"current_draft\"]}, state.update(final_draft=state[\"current_draft\"])\n",
    "\n",
    "\n",
    "def _create_sub_application(\n",
    "    max_num_drafts: int,\n",
    "    spawning_application_context: Optional[ApplicationContext],\n",
    "    poem_type: str,\n",
    "    prompt: str,\n",
    ") -> Application:\n",
    "    \"\"\"Utility to create sub-application -- note\"\"\"\n",
    "    builder = (\n",
    "        ApplicationBuilder()\n",
    "        .with_actions(\n",
    "            edit,\n",
    "            write,\n",
    "            final_draft,\n",
    "        )\n",
    "        .with_transitions(\n",
    "            (\"write\", \"edit\", Condition.expr(f\"num_drafts < {max_num_drafts}\")),\n",
    "            (\"write\", \"final_draft\"),\n",
    "            (\"edit\", \"final_draft\", Condition.expr(\"len(feedback) == 0\")),\n",
    "            (\"edit\", \"write\"),\n",
    "        )\n",
    "        .with_entrypoint(\"write\")\n",
    "        .with_state(\n",
    "            current_draft=None,\n",
    "            poem_type=poem_type,\n",
    "            prompt=prompt,\n",
    "            feedback=None,\n",
    "        )\n",
    "    )\n",
    "    # so we can run without it\n",
    "    if spawning_application_context:\n",
    "        builder=(\n",
    "            builder\n",
    "            .with_tracker(spawning_application_context.tracker.copy())  # remember to do `copy()` here!\n",
    "            .with_spawning_parent(\n",
    "                spawning_application_context.app_id,\n",
    "                spawning_application_context.sequence_id,\n",
    "                spawning_application_context.partition_key,\n",
    "            )\n",
    "        )\n",
    "        \n",
    "    return builder.build()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "52ef53b9-c3a1-4ee4-a8e0-99906c6bd8d8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 8.1.0 (20230707.0739)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"99pt\" height=\"174pt\"\n",
       " viewBox=\"0.00 0.00 98.50 174.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 170)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-170 94.5,-170 94.5,4 -4,4\"/>\n",
       "<!-- edit -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>edit</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M42,-166C42,-166 12,-166 12,-166 6,-166 0,-160 0,-154 0,-154 0,-142 0,-142 0,-136 6,-130 12,-130 12,-130 42,-130 42,-130 48,-130 54,-136 54,-142 54,-142 54,-154 54,-154 54,-160 48,-166 42,-166\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-142.95\" font-family=\"Times,serif\" font-size=\"14.00\">edit</text>\n",
       "</g>\n",
       "<!-- write -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>write</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M42,-101C42,-101 12,-101 12,-101 6,-101 0,-95 0,-89 0,-89 0,-77 0,-77 0,-71 6,-65 12,-65 12,-65 42,-65 42,-65 48,-65 54,-71 54,-77 54,-77 54,-89 54,-89 54,-95 48,-101 42,-101\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-77.95\" font-family=\"Times,serif\" font-size=\"14.00\">write</text>\n",
       "</g>\n",
       "<!-- edit&#45;&gt;write -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>edit&#45;&gt;write</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M20.91,-129.78C20.36,-124.23 20.15,-117.92 20.29,-111.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"23.82,-112.38 20.91,-102.19 16.83,-111.97 23.82,-112.38\"/>\n",
       "</g>\n",
       "<!-- final_draft -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>final_draft</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M78.5,-36C78.5,-36 29.5,-36 29.5,-36 23.5,-36 17.5,-30 17.5,-24 17.5,-24 17.5,-12 17.5,-12 17.5,-6 23.5,0 29.5,0 29.5,0 78.5,0 78.5,0 84.5,0 90.5,-6 90.5,-12 90.5,-12 90.5,-24 90.5,-24 90.5,-30 84.5,-36 78.5,-36\"/>\n",
       "<text text-anchor=\"middle\" x=\"54\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">final_draft</text>\n",
       "</g>\n",
       "<!-- edit&#45;&gt;final_draft -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>edit&#45;&gt;final_draft</title>\n",
       "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M44.84,-129.9C51.94,-121.88 59.3,-111.74 63,-101 68.99,-83.62 66.71,-63.05 62.95,-46.86\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"66.13,-46.22 60.19,-37.45 59.37,-48.01 66.13,-46.22\"/>\n",
       "</g>\n",
       "<!-- write&#45;&gt;edit -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>write&#45;&gt;edit</title>\n",
       "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M33.09,-101.19C33.64,-106.75 33.85,-113.06 33.71,-119.18\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"30.18,-118.6 33.09,-128.78 37.17,-119.01 30.18,-118.6\"/>\n",
       "</g>\n",
       "<!-- write&#45;&gt;final_draft -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>write&#45;&gt;final_draft</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M34.38,-64.78C36.88,-58.95 39.73,-52.29 42.48,-45.89\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"45.91,-47.76 46.63,-37.19 39.47,-45.01 45.91,-47.76\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x16a053210>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "_create_sub_application(2, None, \"sonnet\", \"state machines\").visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f14b1f4-06d2-492c-be5c-088862445ff7",
   "metadata": {},
   "source": [
    "# Full Application\n",
    "\n",
    "Next let's create the actual application. We'll call the sub-application inside the `generate_all_poems` step:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0b786047-8944-45d4-a383-b32ee013a773",
   "metadata": {},
   "outputs": [],
   "source": [
    "# full agent\n",
    "@action(\n",
    "    reads=[],\n",
    "    writes=[\n",
    "        \"max_drafts\",\n",
    "        \"poem_types\",\n",
    "        \"poem_subject\",\n",
    "    ],\n",
    ")\n",
    "def user_input(\n",
    "    state: State, max_drafts: int, poem_types: List[str], poem_subject: str\n",
    ") -> Tuple[dict, State]:\n",
    "    \"\"\"Collects user input for the poem generation process.\"\"\"\n",
    "    return {\n",
    "        \"max_drafts\": max_drafts,\n",
    "        \"poem_types\": poem_types,\n",
    "        \"poem_subject\": poem_subject,\n",
    "    }, state.update(max_drafts=max_drafts, poem_types=poem_types, poem_subject=poem_subject)\n",
    "\n",
    "\n",
    "@action(reads=[\"max_drafts\", \"poem_types\", \"poem_subject\"], writes=[\"proposals\"])\n",
    "def generate_all_poems(state: State, __context: ApplicationContext) -> Tuple[dict, State]:\n",
    "    # create one each\n",
    "    apps = [\n",
    "        _create_sub_application(state[\"max_drafts\"], __context, poem_type, state[\"poem_subject\"])\n",
    "        for poem_type in state[\"poem_types\"]\n",
    "    ]\n",
    "    # run them all in parallel\n",
    "    with parallel_config(backend=\"threading\", n_jobs=3):\n",
    "        all_results = joblib.Parallel()(\n",
    "            joblib.delayed(app.run)(halt_after=[\"final_draft\"])\n",
    "            for app, poem_type in zip(apps, state[\"poem_types\"])\n",
    "        )\n",
    "    proposals = []\n",
    "    for *_, substate in all_results:\n",
    "        proposals.append(substate[\"final_draft\"])\n",
    "\n",
    "    return {\"proposals\": proposals}, state.update(proposals=proposals)\n",
    "\n",
    "\n",
    "@action(reads=[\"proposals\", \"prompts\"], writes=[\"final_results\"])\n",
    "def final_results(state: State) -> Tuple[dict, State]:\n",
    "    # joins them into a string\n",
    "    proposals = state[\"proposals\"]\n",
    "    final_results = \"\\n\\n\".join(\n",
    "        [f\"{poem_type}:\\n{proposal}\" for poem_type, proposal in zip(state[\"poem_types\"], proposals)]\n",
    "    )\n",
    "    return {\"final_results\": final_results}, state.update(final_results=final_results)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "195a5ab3-1208-4200-9e9d-473ec0575e10",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 8.1.0 (20230707.0739)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"532pt\" height=\"239pt\"\n",
       " viewBox=\"0.00 0.00 531.68 239.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 235)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-235 527.68,-235 527.68,4 -4,4\"/>\n",
       "<!-- user_input -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>user_input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M279.51,-166C279.51,-166 230.51,-166 230.51,-166 224.51,-166 218.51,-160 218.51,-154 218.51,-154 218.51,-142 218.51,-142 218.51,-136 224.51,-130 230.51,-130 230.51,-130 279.51,-130 279.51,-130 285.51,-130 291.51,-136 291.51,-142 291.51,-142 291.51,-154 291.51,-154 291.51,-160 285.51,-166 279.51,-166\"/>\n",
       "<text text-anchor=\"middle\" x=\"255.01\" y=\"-142.95\" font-family=\"Times,serif\" font-size=\"14.00\">user_input</text>\n",
       "</g>\n",
       "<!-- generate_all_poems -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>generate_all_poems</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M305.39,-101C305.39,-101 204.64,-101 204.64,-101 198.64,-101 192.64,-95 192.64,-89 192.64,-89 192.64,-77 192.64,-77 192.64,-71 198.64,-65 204.64,-65 204.64,-65 305.39,-65 305.39,-65 311.39,-65 317.39,-71 317.39,-77 317.39,-77 317.39,-89 317.39,-89 317.39,-95 311.39,-101 305.39,-101\"/>\n",
       "<text text-anchor=\"middle\" x=\"255.01\" y=\"-77.95\" font-family=\"Times,serif\" font-size=\"14.00\">generate_all_poems</text>\n",
       "</g>\n",
       "<!-- user_input&#45;&gt;generate_all_poems -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>user_input&#45;&gt;generate_all_poems</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M255.01,-129.78C255.01,-124.23 255.01,-117.92 255.01,-111.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"258.51,-112.19 255.01,-102.19 251.51,-112.19 258.51,-112.19\"/>\n",
       "</g>\n",
       "<!-- input__poem_types -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__poem_types</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"80.01\" cy=\"-213\" rx=\"80.01\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"80.01\" y=\"-207.95\" font-family=\"Times,serif\" font-size=\"14.00\">input: poem_types</text>\n",
       "</g>\n",
       "<!-- input__poem_types&#45;&gt;user_input -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__poem_types&#45;&gt;user_input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M121.04,-197.23C147.11,-187.84 180.93,-175.67 208.07,-165.9\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"208.89,-168.96 217.11,-162.28 206.52,-162.38 208.89,-168.96\"/>\n",
       "</g>\n",
       "<!-- input__max_drafts -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>input__max_drafts</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"255.01\" cy=\"-213\" rx=\"76.94\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"255.01\" y=\"-207.95\" font-family=\"Times,serif\" font-size=\"14.00\">input: max_drafts</text>\n",
       "</g>\n",
       "<!-- input__max_drafts&#45;&gt;user_input -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__max_drafts&#45;&gt;user_input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M255.01,-194.78C255.01,-189.23 255.01,-182.92 255.01,-176.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"258.51,-177.19 255.01,-167.19 251.51,-177.19 258.51,-177.19\"/>\n",
       "</g>\n",
       "<!-- input__poem_subject -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__poem_subject</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"437.01\" cy=\"-213\" rx=\"86.67\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"437.01\" y=\"-207.95\" font-family=\"Times,serif\" font-size=\"14.00\">input: poem_subject</text>\n",
       "</g>\n",
       "<!-- input__poem_subject&#45;&gt;user_input -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>input__poem_subject&#45;&gt;user_input</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M393.88,-197.07C366.26,-187.51 330.42,-175.1 302.07,-165.29\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"303.59,-161.76 292.99,-161.8 301.3,-168.38 303.59,-161.76\"/>\n",
       "</g>\n",
       "<!-- final_results -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>final_results</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M284.39,-36C284.39,-36 225.64,-36 225.64,-36 219.64,-36 213.64,-30 213.64,-24 213.64,-24 213.64,-12 213.64,-12 213.64,-6 219.64,0 225.64,0 225.64,0 284.39,0 284.39,0 290.39,0 296.39,-6 296.39,-12 296.39,-12 296.39,-24 296.39,-24 296.39,-30 290.39,-36 284.39,-36\"/>\n",
       "<text text-anchor=\"middle\" x=\"255.01\" y=\"-12.95\" font-family=\"Times,serif\" font-size=\"14.00\">final_results</text>\n",
       "</g>\n",
       "<!-- generate_all_poems&#45;&gt;final_results -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>generate_all_poems&#45;&gt;final_results</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M255.01,-64.78C255.01,-59.23 255.01,-52.92 255.01,-46.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"258.51,-47.19 255.01,-37.19 251.51,-47.19 258.51,-47.19\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x16a0d8dd0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app = (\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(\n",
    "        user_input,\n",
    "        generate_all_poems,\n",
    "        final_results,\n",
    "    )\n",
    "    .with_transitions(\n",
    "        (\"user_input\", \"generate_all_poems\"),\n",
    "        (\"generate_all_poems\", \"final_results\"),\n",
    "    )\n",
    "    .with_tracker(project=\"demo:parallelism_poem_generation\")\n",
    "    .with_entrypoint(\"user_input\")\n",
    "    .build()\n",
    ")\n",
    "app.visualize()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "8db52375-6031-4b2e-8667-f7bc81f76580",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "[View in UI!](http://localhost:7241/project/demo:parallelism_poem_generation/7e4abaa5-5d9f-4a35-863b-9627727eb4d4) (make sure Burr is running first)"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Markdown\n",
    "Markdown(f\"[View in UI!](http://localhost:7241/project/demo:parallelism_poem_generation/{app.uid}) (make sure Burr is running first)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9700a6a5-b6c8-475c-afaa-96ca2bf2a65b",
   "metadata": {},
   "source": [
    "# Running it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "992c0e25-e504-4eda-8d13-f3ec07aa73ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "action, state, results = app.run(\n",
    "    halt_after=[\"final_results\"],\n",
    "    inputs={\n",
    "        \"max_drafts\": 2,\n",
    "        \"poem_types\": [\n",
    "            \"sonnet\",\n",
    "            \"limerick\",\n",
    "            \"haiku\",\n",
    "            \"acrostic\",\n",
    "        ],\n",
    "        \"poem_subject\": \"state machines\",\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "cb52e66c-b391-4495-aa48-b86fb96fc780",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sonnet:\n",
      "In realms of logic, where machines reside,\n",
      "With gears of reason, wheels of choice aligned,\n",
      "A state machine, our guiding technologic guide,\n",
      "A dance of code within a frame confined.\n",
      "\n",
      "It starts with states, finite list well-traced,\n",
      "Transitions chart its routes from here to there.\n",
      "Encoded paths, in logic's arms embraced,\n",
      "A web of rules, spun tight with utmost care.\n",
      "\n",
      "From idle calm to busy hum it shifts,\n",
      "With each condition met, it alters course.\n",
      "It thrives on change; its power deftly lifts,\n",
      "Transforms through states, a tireless, coded force.\n",
      "\n",
      "Though hardware cold may cloak its silent might,\n",
      "In structured change, it brings our world to light.\n",
      "\n",
      "limerick:\n",
      "In realms where the data aligns,\n",
      "Live machines with sleek, stateful designs.\n",
      "Their transitions, so neat,\n",
      "Make logic a treat,\n",
      "As grand as the royals in lines.\n",
      "\n",
      "haiku:\n",
      "Whispers of logic,\n",
      "Circuits pulse in silent paths —\n",
      "States craft vivid tales.\n",
      "\n",
      "acrostic:\n",
      "**State Machines**\n",
      "\n",
      "**S**hadows of logic in code’s tight embrace,\n",
      "**T**houghts intertwined in a digital space.\n",
      "**A**lchemy of zeros ignites the race,\n",
      "**T**ransitions intricate, guarded with grace.\n",
      "**E**choed whispers in circuits’ high chase.\n",
      "\n",
      "**M**emory’s echo in silicon lanes,\n",
      "**A**cross pathways, breaking old chains.\n",
      "**C**elestial guides in algorithm’s reign,\n",
      "**H**eavy with purpose, binaries plain.\n",
      "**I**nfinite states, each proud and contained,\n",
      "**N**avigating logic, calculations sustained,\n",
      "**E**thos of order where chaos restrains,\n",
      "**S**ymbiotic rhythms, precision regained.\n"
     ]
    }
   ],
   "source": [
    "print(results['final_results'])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
